#include "ntddk.h"
//#include "Vmm.h"
#include "ia32_types.h"
#ifndef __EPT_HEADER__
#define __EPT_HEADER__

union EptPointer {
	ULONG64 all;
	struct {
		ULONG64 memory_type : 3;                      //!< [0:2]
		ULONG64 page_walk_length : 3;                 //!< [3:5]
		ULONG64 enable_accessed_and_dirty_flags : 1;  //!< [6]
		ULONG64 reserved1 : 5;                        //!< [7:11]
		ULONG64 pml4_address : 36;                    //!< [12:48-1]
		ULONG64 reserved2 : 16;                       //!< [48:63]
	} fields;
};
union EptCommonEntry {
	ULONG64 all;
	struct {
		ULONG64 read_access : 1;       //!< [0]
		ULONG64 write_access : 1;      //!< [1]
		ULONG64 execute_access : 1;    //!< [2]
		ULONG64 memory_type : 3;       //!< [3:5]
		ULONG64 reserved1 : 6;         //!< [6:11]
		ULONG64 physial_address : 36;  //!< [12:48-1]
		ULONG64 reserved2 : 16;        //!< [48:63]
	} fields;
};

struct EptData {
	EptPointer ept_pointer;
	EptCommonEntry *ept_pml4;

	EptCommonEntry **preallocated_entries;  // An array of pre-allocated entries
	volatile long preallocated_entries_count;  // # of used pre-allocated entries
};
#endif

void EptInitializeMtrrEntries();
EptData* EptInitialization();
void EptTermination(EptData *ept_data);
EptCommonEntry *EptpConstructTables(EptCommonEntry *table, ULONG table_level, ULONG64 physical_address, EptData *ept_data);
void EptpDestructTables(EptCommonEntry *table, ULONG table_level);
EptCommonEntry *EptpGetEptPtEntry(EptCommonEntry *table, ULONG table_level, ULONG64 physical_address);
EptCommonEntry *EptGetEptPtEntry(EptData *ept_data, ULONG64 physical_address);
void EnableMTF();
void DisableMTF();